package org.example.backend.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.example.backend.common.Result;
import org.example.backend.entity.WeatherAlert;
import org.example.backend.entity.WeatherCurrent;
import org.example.backend.entity.WeatherForecast;
import org.example.backend.mapper.WeatherAlertMapper;
import org.example.backend.mapper.WeatherCurrentMapper;
import org.example.backend.mapper.WeatherForecastMapper;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/weather")
@RequiredArgsConstructor
@Api(tags = "天气API")
public class WeatherController {

    private final WeatherCurrentMapper weatherCurrentMapper;
    private final WeatherForecastMapper weatherForecastMapper;
    private final WeatherAlertMapper weatherAlertMapper;

    @GetMapping("/current/{cityCode}")
    @ApiOperation("获取城市当前天气")
    public Result<WeatherCurrent> getCurrentWeather(
            @ApiParam(value = "城市代码", required = true)
            @PathVariable String cityCode) {
        WeatherCurrent weatherCurrent = weatherCurrentMapper.selectOne(
                new LambdaQueryWrapper<WeatherCurrent>()
                        .eq(WeatherCurrent::getCityCode, cityCode));

        if (weatherCurrent != null) {
            return Result.success(weatherCurrent);
        } else {
            return Result.failed("城市天气数据不存在");
        }
    }

    @GetMapping("/current")
    @ApiOperation("获取所有城市当前天气")
    public Result<List<WeatherCurrent>> getAllCurrentWeather() {
        List<WeatherCurrent> list = weatherCurrentMapper.selectList(null);
        return Result.success(list);
    }

    @GetMapping("/forecast/{cityCode}")
    @ApiOperation("获取城市天气预报")
    public Result<List<WeatherForecast>> getWeatherForecast(
            @ApiParam(value = "城市代码", required = true)
            @PathVariable String cityCode) {
        List<WeatherForecast> list = weatherForecastMapper.selectList(
                new LambdaQueryWrapper<WeatherForecast>()
                        .eq(WeatherForecast::getCityCode, cityCode)
                        .orderByAsc(WeatherForecast::getForecastDate));

        if (!list.isEmpty()) {
            return Result.success(list);
        } else {
            return Result.failed("城市天气预报数据不存在");
        }
    }

    @GetMapping("/alert/{cityCode}")
    @ApiOperation("获取城市天气警报")
    public Result<List<WeatherAlert>> getWeatherAlert(
            @ApiParam(value = "城市代码", required = true)
            @PathVariable String cityCode) {
        List<WeatherAlert> list = weatherAlertMapper.selectList(
                new LambdaQueryWrapper<WeatherAlert>()
                        .eq(WeatherAlert::getCityCode, cityCode)
                        .eq(WeatherAlert::getIsActive, true));

        return Result.success(list);
    }

    @GetMapping("/all/{cityCode}")
    @ApiOperation("获取城市所有天气信息")
    public Result<Map<String, Object>> getAllWeatherInfo(
            @ApiParam(value = "城市代码", required = true)
            @PathVariable String cityCode) {
        Map<String, Object> result = new HashMap<>();

        // 获取当前天气
        WeatherCurrent current = weatherCurrentMapper.selectOne(
                new LambdaQueryWrapper<WeatherCurrent>()
                        .eq(WeatherCurrent::getCityCode, cityCode));

        // 获取天气预报
        List<WeatherForecast> forecast = weatherForecastMapper.selectList(
                new LambdaQueryWrapper<WeatherForecast>()
                        .eq(WeatherForecast::getCityCode, cityCode)
                        .orderByAsc(WeatherForecast::getForecastDate));

        // 获取天气警报
        List<WeatherAlert> alerts = weatherAlertMapper.selectList(
                new LambdaQueryWrapper<WeatherAlert>()
                        .eq(WeatherAlert::getCityCode, cityCode)
                        .eq(WeatherAlert::getIsActive, true));

        result.put("current", current);
        result.put("forecast", forecast);
        result.put("alerts", alerts);

        if (current != null) {
            return Result.success(result);
        } else {
            return Result.failed("城市天气数据不存在");
        }
    }

    @GetMapping("/cities")
    @ApiOperation("获取所有城市代码和名称")
    public Result<List<Map<String, Object>>> getAllCities() {
        List<WeatherCurrent> list = weatherCurrentMapper.selectList(
                new LambdaQueryWrapper<WeatherCurrent>()
                        .select(WeatherCurrent::getCityCode, WeatherCurrent::getCityName));

        List<Map<String, Object>> result = list.stream()
                .map(item -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("code", item.getCityCode());
                    map.put("name", item.getCityName());
                    return map;
                })
                .collect(Collectors.toList());

        return Result.success(result);
    }

    @GetMapping("/search")
    @ApiOperation("根据城市名称搜索")
    public Result<List<WeatherCurrent>> searchByName(
            @ApiParam(value = "城市名称", required = true)
            @RequestParam String name) {
        List<WeatherCurrent> list = weatherCurrentMapper.selectList(
                new LambdaQueryWrapper<WeatherCurrent>()
                        .like(WeatherCurrent::getCityName, name));

        if (!list.isEmpty()) {
            return Result.success(list);
        } else {
            return Result.failed("未找到匹配的城市");
        }
    }

    @GetMapping("/statistics")
    @ApiOperation("获取天气统计信息")
    public Result<Map<String, Object>> getStatistics() {
        Map<String, Object> result = new HashMap<>();

        // 获取城市总数
        long cityCount = weatherCurrentMapper.selectCount(null);

        // 获取警报总数
        long alertCount = weatherAlertMapper.selectCount(
                new LambdaQueryWrapper<WeatherAlert>()
                        .eq(WeatherAlert::getIsActive, true));
        result.put("cityCount", cityCount);
        result.put("alertCount", alertCount);
        return Result.success(result);
    }

    @GetMapping("/hot-cities")
    @ApiOperation("获取热门城市天气")
    public Result<List<WeatherCurrent>> getHotCities() {
        List<WeatherCurrent> list = weatherCurrentMapper.selectList(
                new LambdaQueryWrapper<WeatherCurrent>()
                        .orderByDesc(WeatherCurrent::getTemperature)
                        .last("LIMIT 5"));

        return Result.success(list);
    }

    @GetMapping("/cold-cities")
    @ApiOperation("获取最冷城市天气")
    public Result<List<WeatherCurrent>> getColdCities() {
        List<WeatherCurrent> list = weatherCurrentMapper.selectList(
                new LambdaQueryWrapper<WeatherCurrent>()
                        .orderByAsc(WeatherCurrent::getTemperature)
                        .last("LIMIT 5"));

        return Result.success(list);
    }

    @GetMapping("/temperature-range")
    @ApiOperation("获取特定温度范围内的城市")
    public Result<List<WeatherCurrent>> getCitiesByTemperatureRange(
            @ApiParam(value = "最低温度", required = true)
            @RequestParam BigDecimal minTemp,
            @ApiParam(value = "最高温度", required = true)
            @RequestParam BigDecimal maxTemp) {

        List<WeatherCurrent> list = weatherCurrentMapper.selectList(
                new LambdaQueryWrapper<WeatherCurrent>()
                        .ge(WeatherCurrent::getTemperature, minTemp)
                        .le(WeatherCurrent::getTemperature, maxTemp));

        if (!list.isEmpty()) {
            return Result.success(list);
        } else {
            return Result.failed("未找到温度范围内的城市");
        }
    }

    @GetMapping("/forecast/date/{cityCode}")
    @ApiOperation("获取指定日期的天气预报")
    public Result<WeatherForecast> getForecastByDate(
            @ApiParam(value = "城市代码", required = true)
            @PathVariable String cityCode,
            @ApiParam(value = "预报日期(yyyy-MM-dd)", required = true)
            @RequestParam String date) {

        try {
            LocalDate forecastDate = LocalDate.parse(date);

            WeatherForecast forecast = weatherForecastMapper.selectOne(
                    new LambdaQueryWrapper<WeatherForecast>()
                            .eq(WeatherForecast::getCityCode, cityCode)
                            .eq(WeatherForecast::getForecastDate, forecastDate));

            if (forecast != null) {
                return Result.success(forecast);
            } else {
                return Result.failed("未找到指定日期的天气预报");
            }
        } catch (Exception e) {
            return Result.validateFailed("日期格式不正确，请使用yyyy-MM-dd格式");
        }
    }

    @GetMapping("/weather-condition/{condition}")
    @ApiOperation("获取特定天气状况的城市")
    public Result<List<WeatherCurrent>> getCitiesByWeatherCondition(
            @ApiParam(value = "天气状况(如：晴、多云、雨等)", required = true)
            @PathVariable String condition) {

        List<WeatherCurrent> list = weatherCurrentMapper.selectList(
                new LambdaQueryWrapper<WeatherCurrent>()
                        .like(WeatherCurrent::getWeatherCondition, condition));

        if (!list.isEmpty()) {
            return Result.success(list);
        } else {
            return Result.failed("未找到天气状况为：" + condition + " 的城市");
        }
    }

    @PostMapping("/compare")
    @ApiOperation("比较多个城市的天气")
    public Result<Map<String, List<WeatherCurrent>>> compareCities(
            @ApiParam(value = "城市代码列表", required = true)
            @RequestBody List<String> cityCodes) {

        if (cityCodes == null || cityCodes.isEmpty()) {
            return Result.validateFailed("城市代码列表不能为空");
        }

        List<WeatherCurrent> list = weatherCurrentMapper.selectList(
                new LambdaQueryWrapper<WeatherCurrent>()
                        .in(WeatherCurrent::getCityCode, cityCodes));

        Map<String, List<WeatherCurrent>> result = new HashMap<>();
        result.put("cities", list);

        return Result.success(result);
    }
}
